package com.example.springboot.endpoint.server;

import com.example.springboot.endpoint.config.WebSocketConfig;
import org.springframework.stereotype.Component;

import javax.websocket.CloseReason;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.PongMessage;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

/**
 * ServerEndpoint 用于声明一个 WebSocket 服务端 endpoint
 * <p> Component 注解声明 WebSocketSever，是一个bean,方便使用Autowired方式注入
 * <p> 但是仅使用 Component 不能让spring容器管理， 需要spring的ServerEndpointExporter来桥接
 * <p>
 *
 * @author Zhang.Z
 * @version 2025-09-21
 *
 * @see WebSocketConfig
 */
@Component
@ServerEndpoint(value = "/ws")
public class WebSocketServerEndpoint {


    /**
     * 当客户端与服务端建立 WebSocket 连接时触发。
     * <p> 可以在这里保存 Session，初始化资源
     */
    @OnOpen
    public void onOpen(Session session) throws Exception {

        // 获取 URL 参数
        Map<String, List<String>> params = session.getRequestParameterMap();

        if (params.containsKey("userId")) {
            System.out.printf("userId = {%s} 建立连接%n", params.get("userId"));
        }else {
            System.out.printf("websocket.id={%s}建立连接%n", session.getId());
        }

    }


    /**
     * 接收到文本消息时触发
     */
    @OnMessage
    public void onTextMessage(String message, Session session) throws Exception {
        System.out.println(session.getId() + " : " + message);
        //发送数据
        session.getBasicRemote().sendText(LocalDateTime.now().toString());
    }

    /**
     * 接收到二进制消息时触发
     */
    @OnMessage
    public void onBinaryMessage(ByteBuffer message, Session session) {
        System.out.println("收到二进制: " + message.remaining() + " bytes");
    }

    /**
     * 接收到 Pong 消息时触发 (响应 ping)
     */
    @OnMessage
    public void onPongMessage(PongMessage pong, Session session) {
        System.out.println("收到 Pong");
    }


    /**
     * 当连接关闭时触发。可以做清理工作，例如移除 session。
     */
    @OnClose
    public void onClose(Session session, CloseReason reason) throws IOException {

        System.out.printf("websocket.id={%s}关闭链接%s", session.getId(), reason.getReasonPhrase());

        if (session.isOpen()) {
            session.close();
        }
    }


    /**
     * 当发生错误（如 IO 异常、编码异常）时触发
     */
    @OnError
    public void OnError(Session session, Throwable throwable) {
        System.out.printf("【%s】 链接异常, %s%n", session.getId(), throwable.getMessage());
    }
}
